/*
 * Yet Another Haxe Library, Copyright (c) 2009, Jean-Philippe CIMAN (Jeanffy)
 * All rights reserved.
 * Permission is hereby granted to use, copy, modify, and distribute this
 * source code, or portions hereof, for any purpose, without fee, subject
 * to the following restrictions:
 *
 * 1. The origin of this source code must not be misrepresented.
 * 2. Altered versions must be plainly marked as such and
 *    must not be misrepresented as being the original source.
 * 3. This copyright notice may not be removed or altered from
 *    any source or altered source distribution.
 *
 * If you use this source code in a product, acknowledgment is not
 * required but would be appreciated.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE PROJECT AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#if flash8
import flash.MovieClip;
#elseif flash9
import flash.display.MovieClip;
#else
	#error
#end

/**
	<p>
	This class is intended to deal with tweening
	</p>
	<p>
	Sample usage :<br/>
	<br/>
	<pre>
	class ToBeTweened extends YahTween
	{
		public function tweenIt()
		{
			setEndTween(onEndTween);
			setCountFrames(10); // to tween in 10 frames long
			setPosition(0, 0, 35, 0); // to tween from position (0,0) to position (35,0)
			setSize(75, 100, 5, 100); // to tween from size (75,100) to size (5,100)
			setAlpha(100, 50); // to tween from alpha 100 to alpha 50
			startTween(); // begin tween, will call onEndTween when the tween is finished
		}
		
		public function onEndTween()
		{
			trace("End tween");
		}
	}
	</pre>
**/
class YahTween extends MovieClip
{
	private var m_callback:Void->Void;
	
	private var m_currentFrame:Int;
	private var m_countFrames:Int;
	
	private var m_startX:Float;
	private var m_startY:Float;
	private var m_endX:Float;
	private var m_endY:Float;
	private var m_startAlpha:Float;
	private var m_endAlpha:Float;
	private var m_startWidth:Float;
	private var m_endWidth:Float;
	private var m_startHeight:Float;
	private var m_endHeight:Float;
	
	private var m_distance:Float;
	private var m_coeff:Float;
	private var m_dirX:Float;
	private var m_dirY:Float;
	private var m_alphaMove:Float;
	private var m_widthMove:Float;
	private var m_heightMove:Float;

	public function new()
	{
#if flash9
		super();
#end
		m_callback = null;
#if flash8
		onEnterFrame = null;
#end
		
		m_currentFrame = 0;
		m_countFrames = 1;
		
#if flash8
		m_startX = _x;
		m_startY = _y;
		m_endX = _x;
		m_endY = _y;
		m_startAlpha = _alpha;
		m_endAlpha = _alpha;
		m_startWidth = _width;
		m_endWidth = _width;
		m_startHeight = _height;
		m_endHeight = _height;
#elseif flash9
		m_startX = x;
		m_startY = y;
		m_endX = x;
		m_endY = y;
		m_startAlpha = alpha;
		m_endAlpha = alpha;
		m_startWidth = width;
		m_endWidth = width;
		m_startHeight = height;
		m_endHeight = height;
#end
		
		m_distance = 0;
		m_coeff = 0;
		m_dirX = 0;
		m_dirY = 0;
		m_alphaMove = 0;
		m_widthMove = 0;
		m_heightMove = 0;
	}

	/** Defines the callback for the end of tween **/
	public function setEndTween(fcallback:Void->Void)
	{
		m_callback = fcallback;
	}
	
	/** Defines the starting and ending position of the movieclip **/
	public function setPosition(startX:Float, startY:Float, endX:Float, endY:Float)
	{
		m_startX = startX;
		m_startY = startY;
		m_endX = endX;
		m_endY = endY;
	}
	
	/** Defines the starting and ending alpha of the movieclip **/
	public function setAlpha(startAlpha:Float, endAlpha:Float)
	{
		m_startAlpha = startAlpha;
		m_endAlpha = endAlpha;
	}
	
	/** Defines the starting and ending size of the movieclip **/
	public function setSize(startW:Float, startH:Float, endW:Float, endH:Float)
	{
		m_startWidth = startW;
		m_startHeight = startH;
		m_endWidth = endW;
		m_endHeight = endH;
	}

	/** Defines the number of frames in which the tween will play **/
	public function setCountFrames(nFrames:Int)
	{
		m_countFrames = nFrames;
	}
	
	/** Function that will be called for each frame when tweening is started **/
#if flash8
	private function forEachFrame()
#elseif flash9
	private function forEachFrame(event:flash.events.Event)
#end
	{	
		m_currentFrame++;
#if flash8
		_x += m_dirX * m_coeff;
		_y += m_dirY * m_coeff;
		_alpha += m_alphaMove;
		_width += m_widthMove;
		_height += m_heightMove;
		if (m_currentFrame >= m_countFrames)
		{
			onEnterFrame = null;
			m_callback();
		}
#elseif flash9
		x += m_dirX * m_coeff;
		y += m_dirY * m_coeff;
		alpha += m_alphaMove;
		width += m_widthMove;
		height += m_heightMove;
		if (m_currentFrame >= m_countFrames)
		{
			removeEventListener(flash.events.Event.ENTER_FRAME, forEachFrame);
			m_callback();
		}
#end
	}
	
	/** Starts the tweening **/
	public function startTween()
	{
		m_dirX = m_endX - m_startX;
		m_dirY = m_endY - m_startY;
		m_distance = Math.sqrt(m_dirX*m_dirX + m_dirY*m_dirY);
		if (m_distance != 0)
		{
			m_dirX /= m_distance;
			m_dirY /= m_distance;
		}
	
		m_coeff = m_distance / m_countFrames;
		m_alphaMove = (m_endAlpha-m_startAlpha) / m_countFrames;
		m_widthMove = (m_endWidth-m_startWidth) / m_countFrames;
		m_heightMove = (m_endHeight-m_startHeight) / m_countFrames;
#if flash8
		_x = m_startX;
		_y = m_startY;
		_alpha = m_startAlpha;
		_width = m_startWidth;
		_height = m_startHeight;
#elseif flash9
		x = m_startX;
		y = m_startY;
		alpha = m_startAlpha;
		width = m_startWidth;
		height = m_startHeight;
#end
		m_currentFrame = 0;

#if flash8
		onEnterFrame = forEachFrame;
#elseif flash9
		addEventListener(flash.events.Event.ENTER_FRAME, forEachFrame);
#end
	}
}
